home *** CD-ROM | disk | FTP | other *** search
/ The Utilities Experience / The Utilities Experience - Volume 1.iso / software / misc / o-z / x-windows / mesa-amiwin / src / xform.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-30  |  24.3 KB  |  973 lines

  1. /* xform.c */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  1.2
  6.  * Copyright (C) 1995  Brian Paul  (brianp@ssec.wisc.edu)
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25. $Id: xform.c,v 1.22 1995/10/31 19:40:35 brianp Exp $
  26.  
  27. $Log: xform.c,v $
  28.  * Revision 1.22  1995/10/31  19:40:35  brianp
  29.  * removed INLINE macro, more trouble than it was worth
  30.  *
  31.  * Revision 1.21  1995/10/16  15:26:56  brianp
  32.  * replaced dd_buffer_info with DD.buffer_size call
  33.  *
  34.  * Revision 1.20  1995/09/30  15:35:13  brianp
  35.  * added test for identity texture matrix in gl_mult_matrix
  36.  *
  37.  * Revision 1.19  1995/09/27  18:31:40  brianp
  38.  * added gl_transform_normals
  39.  *
  40.  * Revision 1.18  1995/09/26  16:05:26  brianp
  41.  * removed gl_transform_point, gl_transform_normal
  42.  * added gl_transform_points
  43.  *
  44.  * Revision 1.17  1995/09/13  14:42:23  brianp
  45.  * added logic to test for identity texture matrix
  46.  *
  47.  * Revision 1.16  1995/07/24  20:35:20  brianp
  48.  * replaced memset() with MEMSET() and memcpy() with MEMCPY()
  49.  *
  50.  * Revision 1.15  1995/07/24  18:58:28  brianp
  51.  * correct gl_viewport() semantics, introduced CC.ClipSpans flag
  52.  *
  53.  * Revision 1.14  1995/06/21  15:11:08  brianp
  54.  * better allocation policy for depth, stencil buffer in gl_viewport
  55.  *
  56.  * Revision 1.13  1995/06/20  16:26:32  brianp
  57.  * removed fudge value from viewport transformation scale and translation
  58.  *
  59.  * Revision 1.12  1995/05/22  21:02:41  brianp
  60.  * Release 1.2
  61.  *
  62.  * Revision 1.11  1995/05/12  16:57:22  brianp
  63.  * replaced CC.Mode!=0 with INSIDE_BEGIN_END
  64.  *
  65.  * Revision 1.10  1995/04/19  13:48:18  brianp
  66.  * renamed occurances of near and far for SCO x86 Unix
  67.  *
  68.  * Revision 1.9  1995/04/01  16:17:47  brianp
  69.  * fixed mult_matrix bug in glTranslatef and glScalef
  70.  *
  71.  * Revision 1.8  1995/03/28  16:10:33  brianp
  72.  * removed singular matrix error message
  73.  *
  74.  * Revision 1.7  1995/03/22  21:37:47  brianp
  75.  * removed mode from dd_buffer_info()
  76.  *
  77.  * Revision 1.6  1995/03/10  17:13:20  brianp
  78.  * new matmul and invert_matrix functions from Thomas Malik
  79.  *
  80.  * Revision 1.5  1995/03/10  15:19:43  brianp
  81.  * added divide by zero check to gl_transform_normal
  82.  *
  83.  * Revision 1.4  1995/03/09  21:42:30  brianp
  84.  * new ModelViewInv matrix logic
  85.  *
  86.  * Revision 1.3  1995/03/09  20:08:48  brianp
  87.  * changed order of arguments to gl_transform_ functions to be more logical
  88.  *
  89.  * Revision 1.2  1995/03/04  19:29:44  brianp
  90.  * 1.1 beta revision
  91.  *
  92.  * Revision 1.1  1995/02/24  14:28:31  brianp
  93.  * Initial revision
  94.  *
  95.  */
  96.  
  97.  
  98. /*
  99.  * Geometry Transformation.
  100.  *
  101.  *
  102.  * NOTES:
  103.  * 1. 4x4 transformation matrices are stored in memory in column major order.
  104.  * 2. Points/vertices are to be thought of as column vectors.
  105.  * 3. Transformation of a point p by a matrix M is: p' = M * p
  106.  *
  107.  */
  108.  
  109.  
  110.  
  111. #include <math.h>
  112. #include <stdio.h>
  113. #include <stdlib.h>
  114. #include <string.h>
  115. #include "context.h"
  116. #include "depth.h"
  117. #include "dd.h"
  118. #include "list.h"
  119. #include "macros.h"
  120. #include "stencil.h"
  121.  
  122.  
  123.  
  124. #ifndef M_PI
  125. #  define M_PI (3.1415926)
  126. #endif
  127.  
  128.  
  129.  
  130. static GLfloat Identity[16] = {
  131.    1.0, 0.0, 0.0, 0.0,
  132.    0.0, 1.0, 0.0, 0.0,
  133.    0.0, 0.0, 1.0, 0.0,
  134.    0.0, 0.0, 0.0, 1.0
  135. };
  136.  
  137.  
  138.  
  139.  
  140. #ifdef DEBUG
  141. static void print_matrix( const GLfloat m[16] )
  142. {
  143.    int i;
  144.  
  145.    for (i=0;i<4;i++) {
  146.       printf("%f %f %f %f\n", m[i], m[4+i], m[8+i], m[12+i] );
  147.    }
  148. }
  149. #endif
  150.  
  151.  
  152.  
  153. /*
  154.  * Perform a 4x4 matrix multiplication  (product = a x b).
  155.  * Input:  a, b - matrices to multiply
  156.  * Output:  product - product of a and b
  157.  */
  158. static void
  159. matmul( GLfloat *product, const GLfloat *a, const GLfloat *b )
  160. {
  161.    /* This matmul was contributed by Thomas Malik */
  162.    GLfloat temp[16];
  163.    GLint i;
  164.  
  165. #define A(row,col)  a[(col<<2)+row]
  166. #define B(row,col)  b[(col<<2)+row]
  167. #define T(row,col)  temp[(col<<2)+row]
  168.  
  169.    /* i-te Zeile */
  170.    for (i = 0; i < 4; i++)
  171.      {
  172.     T(i, 0) = A(i, 0) * B(0, 0) + A(i, 1) * B(1, 0) + A(i, 2) * B(2, 0) + A(i, 3) * B(3, 0);
  173.     T(i, 1) = A(i, 0) * B(0, 1) + A(i, 1) * B(1, 1) + A(i, 2) * B(2, 1) + A(i, 3) * B(3, 1);
  174.     T(i, 2) = A(i, 0) * B(0, 2) + A(i, 1) * B(1, 2) + A(i, 2) * B(2, 2) + A(i, 3) * B(3, 2);
  175.     T(i, 3) = A(i, 0) * B(0, 3) + A(i, 1) * B(1, 3) + A(i, 2) * B(2, 3) + A(i, 3) * B(3, 3);
  176.      }
  177.  
  178. #undef A
  179. #undef B
  180. #undef T
  181.    MEMCPY( product, temp, 16*sizeof(GLfloat) );
  182. }
  183.  
  184.  
  185.  
  186. /*
  187.  * Find the inverse of the 4 by 4 matrix b using gausian elimination
  188.  * and return it in a.
  189.  *
  190.  * This function was contributed by Thomas Malik (malik@rhrk.uni-kl.de).
  191.  * Thanks Thomas!
  192.  */
  193. static void invert_matrix(const GLfloat *b,GLfloat * a)
  194. {
  195. #define MAT(m,r,c) ((m)[(c)*4+(r)])
  196.  
  197.   GLfloat val, val2;
  198.   GLint   i, j, k, ind;
  199.   GLfloat tmp[16];
  200.  
  201.   MEMCPY(a,Identity,sizeof(float)*16);
  202.   MEMCPY(tmp, b,sizeof(float)*16);
  203.  
  204.   for (i = 0; i != 4; i++) {
  205.  
  206.     val = MAT(tmp,i,i);            /* find pivot */
  207.     ind = i;
  208.     for (j = i + 1; j != 4; j++) {
  209.       if (fabs(MAT(tmp,j,i)) > fabs(val)) {
  210.     ind = j;
  211.     val = MAT(tmp,j,i);
  212.       }
  213.     }
  214.  
  215.     if (ind != i) {            /* swap columns */
  216.       for (j = 0; j != 4; j++) {
  217.     val2 = MAT(a,i,j);
  218.     MAT(a,i,j) = MAT(a,ind,j);
  219.     MAT(a,ind,j) = val2;
  220.     val2 = MAT(tmp,i,j);
  221.     MAT(tmp,i,j) = MAT(tmp,ind,j);
  222.     MAT(tmp,ind,j) = val2;
  223.       }
  224.     }
  225.  
  226.     if (val == 0.0F) {    
  227.        /* The matrix is singular (has no inverse).  This isn't really
  228.     * an error since singular matrices can be used for projecting
  229.     * shadows, etc.  We let the inverse be the identity matrix.
  230.     */
  231.        /*fprintf(stderr,"Singular matrix, no inverse!\n");*/
  232.        MEMCPY( a, Identity, 16*sizeof(GLfloat) );
  233.        return;
  234.     }
  235.  
  236.     for (j = 0; j != 4; j++) {
  237.       MAT(tmp,i,j) /= val;
  238.       MAT(a,i,j) /= val;
  239.     }
  240.  
  241.     for (j = 0; j != 4; j++) {        /* eliminate column */
  242.       if (j == i)
  243.     continue;
  244.       val = MAT(tmp,j,i);
  245.       for (k = 0; k != 4; k++) {
  246.     MAT(tmp,j,k) -= MAT(tmp,i,k) * val;
  247.     MAT(a,j,k) -= MAT(a,i,k) * val;
  248.       }
  249.     }
  250.   }
  251. #undef MAT
  252. }
  253.  
  254.  
  255.  
  256.  
  257. /*
  258.  * Compute the inverse of the current ModelViewMatrix.
  259.  */
  260. void gl_compute_modelview_inverse( void )
  261. {
  262.    invert_matrix( CC.ModelViewMatrix, CC.ModelViewInv );
  263.    CC.ModelViewInvValid = GL_TRUE;
  264. }
  265.  
  266.  
  267.  
  268. /*
  269.  * Apply a transformation matrix to an array of coordinates:
  270.  *   for i in 0 to n-1 do   q[i] = m * p[i]
  271.  * where p[i] and q[i] are 4-element column vectors and m is a 16-element
  272.  * transformation matrix.
  273.  */
  274. void gl_transform_points( GLuint n, GLfloat q[][4], const GLfloat m[16],
  275.                           GLfloat p[][4] )
  276. {
  277.    /* This function has been carefully crafted to maximize register usage
  278.     * and use loop unrolling with IRIX 5.3's cc.  Hopefully other compilers
  279.     * will like this code too.
  280.     */
  281.    {
  282.       GLuint i;
  283.       GLfloat m0 = m[0];
  284.       GLfloat m4 = m[4];
  285.       GLfloat m8 = m[8];
  286.       GLfloat m12 = m[12];
  287.       GLfloat m1 = m[1];
  288.       GLfloat m5 = m[5];
  289.       GLfloat m9 = m[9];
  290.       GLfloat m13 = m[13];
  291.       for (i=0;i<n;i++) {
  292.          GLfloat p0 = p[i][0], p1 = p[i][1], p2 = p[i][2], p3 = p[i][3];
  293.          q[i][0] = m0 * p0 + m4  * p1 + m8 * p2 + m12 * p3;
  294.          q[i][1] = m1 * p0 + m5  * p1 + m9 * p2 + m13 * p3;
  295.       }
  296.    }
  297.    {
  298.       GLuint i;
  299.       GLfloat m2 = m[2];
  300.       GLfloat m6 = m[6];
  301.       GLfloat m10 = m[10];
  302.       GLfloat m14 = m[14];
  303.       GLfloat m3 = m[3];
  304.       GLfloat m7 = m[7];
  305.       GLfloat m11 = m[11];
  306.       GLfloat m15 = m[15];
  307.       for (i=0;i<n;i++) {
  308.          GLfloat p0 = p[i][0], p1 = p[i][1], p2 = p[i][2], p3 = p[i][3];
  309.          q[i][2] = m2 * p0 + m6 * p1 + m10 * p2 + m14 * p3;
  310.          q[i][3] = m3 * p0 + m7 * p1 + m11 * p2 + m15 * p3;
  311.       }
  312.    }
  313. }
  314.  
  315.  
  316.  
  317. /*
  318.  * Apply a transformation matrix to an array of normal vectors:
  319.  *   for i in 0 to n-1 do  v[i] = u[i] * m
  320.  * where u[i] and v[i] are 3-element row vectors and m is a 16-element
  321.  * transformation matrix.
  322.  * If the normalize flag is true the normals will be scaled to length 1.
  323.  */
  324. void gl_transform_normals( GLuint n, GLfloat v[][3], const GLfloat m[16],
  325.                            GLfloat u[][3], GLboolean normalize )
  326. {
  327.    if (normalize) {
  328.       /* Transform normals and scale to unit length */
  329.       GLuint i;
  330.       GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8];
  331.       GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9];
  332.       GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10];
  333.       for (i=0;i<n;i++) {
  334.          GLdouble tx, ty, tz;
  335.          {
  336.             GLfloat ux = u[i][0],  uy = u[i][1],  uz = u[i][2];
  337.             tx = ux * m0 + uy * m1 + uz * m2;
  338.             ty = ux * m4 + uy * m5 + uz * m6;
  339.             tz = ux * m8 + uy * m9 + uz * m10;
  340.          }
  341.          {
  342.             GLdouble len, scale;
  343.             len = sqrt( tx*tx + ty*ty + tz*tz );
  344.             scale = (len>0.00001) ? (1.0 / len) : 1.0;
  345.             v[i][0] = tx * scale;
  346.             v[i][1] = ty * scale;
  347.             v[i][2] = tz * scale;
  348.          }
  349.       }
  350.    }
  351.    else {
  352.       /* Just transform normals, don't scale */
  353.       GLuint i;
  354.       GLfloat m0 = m[0],  m4 = m[4],  m8 = m[8];
  355.       GLfloat m1 = m[1],  m5 = m[5],  m9 = m[9];
  356.       GLfloat m2 = m[2],  m6 = m[6],  m10 = m[10];
  357.       for (i=0;i<n;i++) {
  358.          GLfloat ux = u[i][0],  uy = u[i][1],  uz = u[i][2];
  359.          v[i][0] = ux * m0 + uy * m1 + uz * m2;
  360.          v[i][1] = ux * m4 + uy * m5 + uz * m6;
  361.          v[i][2] = ux * m8 + uy * m9 + uz * m10;
  362.       }
  363.    }
  364. }
  365.  
  366.  
  367.  
  368. /*
  369.  * Transform a 4-element row vector (1x4 matrix) by a 4x4 matrix.  This
  370.  * function is used for transforming clipping plane equations and spotlight
  371.  * directions.
  372.  * Mathematically,  u = v * m.
  373.  * Input:  v - input vector
  374.  *         m - transformation matrix
  375.  * Output:  u - transformed vector
  376.  */
  377. void gl_transform_vector( GLfloat u[4], const GLfloat v[4], const GLfloat m[16] )
  378. {
  379. #define M(row,col)  m[col*4+row]
  380.    u[0] = v[0] * M(0,0) + v[1] * M(1,0) + v[2] * M(2,0) + v[3] * M(3,0);
  381.    u[1] = v[0] * M(0,1) + v[1] * M(1,1) + v[2] * M(2,1) + v[3] * M(3,1);
  382.    u[2] = v[0] * M(0,2) + v[1] * M(1,2) + v[2] * M(2,2) + v[3] * M(3,2);
  383.    u[3] = v[0] * M(0,3) + v[1] * M(1,3) + v[2] * M(2,3) + v[3] * M(3,3);
  384. #undef M
  385. }
  386.  
  387.  
  388.  
  389. void glMatrixMode( GLenum mode )
  390. {
  391.    if (INSIDE_BEGIN_END) {
  392.       gl_error( GL_INVALID_OPERATION, "glMatrixMode" );
  393.       return;
  394.    }
  395.  
  396.    switch (mode) {
  397.       case GL_MODELVIEW:
  398.       case GL_PROJECTION:
  399.       case GL_TEXTURE:
  400.          if (CC.CompileFlag) {
  401.         gl_save_set_enum( &CC.Transform.MatrixMode, mode );
  402.      }
  403.      if (CC.ExecuteFlag) {
  404.         CC.Transform.MatrixMode = mode;
  405.      }
  406.      break;
  407.       default:
  408.      gl_error( GL_INVALID_ENUM, "glMatrixMode" );
  409.    }
  410. }
  411.  
  412.  
  413.  
  414. void glOrtho( GLdouble left, GLdouble right,
  415.           GLdouble bottom, GLdouble top,
  416.           GLdouble nearval, GLdouble farval )
  417. {
  418.    GLfloat x, y, z;
  419.    GLfloat tx, ty, tz;
  420.    GLfloat m[16];
  421.  
  422.    x = 2.0 / (right-left);
  423.    y = 2.0 / (top-bottom);
  424.    z = -2.0 / (farval-nearval);
  425.    tx = -(right+left) / (right-left);
  426.    ty = -(top+bottom) / (top-bottom);
  427.    tz = -(farval+nearval) / (farval-nearval);
  428.  
  429. #define M(row,col)  m[col*4+row]
  430.    M(0,0) = x;     M(0,1) = 0.0F;  M(0,2) = 0.0F;  M(0,3) = tx;
  431.    M(1,0) = 0.0F;  M(1,1) = y;     M(1,2) = 0.0F;  M(1,3) = ty;
  432.    M(2,0) = 0.0F;  M(2,1) = 0.0F;  M(2,2) = z;     M(2,3) = tz;
  433.    M(3,0) = 0.0F;  M(3,1) = 0.0F;  M(3,2) = 0.0F;  M(3,3) = 1.0F;
  434. #undef M
  435.  
  436.    glMultMatrixf( m );
  437. }
  438.  
  439.  
  440.  
  441. void glFrustum( GLdouble left, GLdouble right,
  442.         GLdouble bottom, GLdouble top,
  443.         GLdouble nearval, GLdouble farval )
  444. {
  445.    GLfloat x, y, a, b, c, d;
  446.    GLfloat m[16];
  447.  
  448.    if (nearval<=0.0 || farval<=0.0) {
  449.       gl_error( GL_INVALID_VALUE, "glFrustum(near or far)" );
  450.    }
  451.  
  452.    x = (2.0*nearval) / (right-left);
  453.    y = (2.0*nearval) / (top-bottom);
  454.    a = (right+left) / (right-left);
  455.    b = (top+bottom) / (top-bottom);
  456.    c = -(farval+nearval) / ( farval-nearval);
  457.    d = -(2.0*farval*nearval) / (farval-nearval);  /* error? */
  458.  
  459. #define M(row,col)  m[col*4+row]
  460.    M(0,0) = x;     M(0,1) = 0.0F;  M(0,2) = a;      M(0,3) = 0.0F;
  461.    M(1,0) = 0.0F;  M(1,1) = y;     M(1,2) = b;      M(1,3) = 0.0F;
  462.    M(2,0) = 0.0F;  M(2,1) = 0.0F;  M(2,2) = c;      M(2,3) = d;
  463.    M(3,0) = 0.0F;  M(3,1) = 0.0F;  M(3,2) = -1.0F;  M(3,3) = 0.0F;
  464. #undef M
  465.  
  466.    glMultMatrixf( m );
  467. }
  468.  
  469.  
  470.  
  471. /*
  472.  * Define a new viewport and reallocate auxillary buffers if the size of
  473.  * the window (color buffer) has changed.
  474.  */
  475. void gl_viewport( GLint x, GLint y, GLsizei width, GLsizei height )
  476. {
  477.    GLint newsize;
  478.    GLuint buf_width, buf_height, buf_depth;
  479.  
  480.    if (width<0 || height<0) {
  481.       gl_error( GL_INVALID_VALUE, "glViewport" );
  482.       return;
  483.    }
  484.    if (INSIDE_BEGIN_END) {
  485.       gl_error( GL_INVALID_OPERATION, "glViewport" );
  486.       return;
  487.    }
  488.  
  489. #ifdef LEAVEOUT
  490.    /* clamp x, y, width, and height to implementation dependent range */
  491.    x = CLAMP( x, 0, MAX_WIDTH-1 );
  492.    y = CLAMP( y, 0, MAX_HEIGHT-1 );
  493.    if (width<1) {
  494.       width = 1;
  495.    }
  496.    if (height<1) {
  497.       height = 1;
  498.    }
  499.    if (x+width>MAX_WIDTH) {
  500.       width = MAX_WIDTH - x;
  501.    }
  502.    if (y+height>MAX_HEIGHT) {
  503.       height = MAX_HEIGHT - y;
  504.    }
  505. #endif
  506.  
  507.    /* ask device driver for size of output buffer */
  508.    (*DD.buffer_size)( &buf_width, &buf_height, &buf_depth );
  509.  
  510.    /* see if size of device driver buffer has changed */
  511.    newsize = CC.BufferWidth!=buf_width || CC.BufferHeight!=buf_height;
  512.  
  513.    /* save buffer size */
  514.    CC.BufferWidth = buf_width;
  515.    CC.BufferHeight = buf_height;
  516.  
  517.    /* Save viewport */
  518.    CC.Viewport.X = x;
  519.    CC.Viewport.Width = width;
  520.    CC.Viewport.Y = y;
  521.    CC.Viewport.Height = height;
  522.  
  523.    /* compute scale and bias values */
  524.    CC.Viewport.Sx = (GLfloat) width / 2.0F;
  525.    CC.Viewport.Tx = CC.Viewport.Sx + x;
  526.    CC.Viewport.Sy = (GLfloat) height / 2.0F;
  527.    CC.Viewport.Ty = CC.Viewport.Sy + y;
  528.  
  529.    /* Reallocate other buffers if needed. */
  530.    if (newsize && CC.DepthBuffer) {
  531.       /* reallocate depth buffer, if there is one */
  532.       gl_alloc_depth_buffer();
  533.    }
  534.    if (newsize && CC.StencilBuffer) {
  535.       /* reallocate stencil buffer, if there is one */
  536.       gl_alloc_stencil_buffer();
  537.    }
  538.    if (newsize && CC.AccumBuffer) {
  539.       /* Deallocate the accumulation buffer.  A new one will be allocated */
  540.       /* if/when glAccum() is called again. */
  541.       free( CC.AccumBuffer );
  542.       CC.AccumBuffer = NULL;
  543.    }
  544.  
  545.    /* If viewport extends beyond window bounds we have to clip pixel spans */
  546.    if (x<0 || y<0 || x+width>CC.BufferWidth || y+height>CC.BufferHeight) {
  547.       CC.ClipSpans = GL_TRUE;
  548.    }
  549.    else {
  550.       CC.ClipSpans = GL_FALSE;
  551.    }
  552. }
  553.  
  554.  
  555.  
  556. void glViewport( GLint x, GLint y, GLsizei width, GLsizei height )
  557. {
  558.    if (CC.ExecuteFlag) {
  559.       gl_viewport( x, y, width, height );
  560.    }
  561.    if (CC.CompileFlag) {
  562.       gl_save_viewport( x, y, width, height );
  563.    }
  564. }
  565.  
  566.  
  567.  
  568.  
  569. /*
  570.  * Determine if the given matrix is the identity matrix.
  571.  */
  572. static GLboolean is_identity( const GLfloat m[16] )
  573. {
  574.    if (   m[0]==1.0F && m[4]==0.0F && m[ 8]==0.0F && m[12]==0.0F
  575.        && m[1]==0.0F && m[5]==1.0F && m[ 9]==0.0F && m[13]==0.0F
  576.        && m[2]==0.0F && m[6]==0.0F && m[10]==1.0F && m[14]==0.0F
  577.        && m[3]==0.0F && m[7]==0.0F && m[11]==0.0F && m[15]==1.0F) {
  578.       return GL_TRUE;
  579.    }
  580.    else {
  581.       return GL_FALSE;
  582.    }
  583. }
  584.  
  585.  
  586.  
  587.  
  588. void glPushMatrix( void )
  589. {
  590.    if (CC.CompileFlag) {
  591.       gl_save_pushmatrix();
  592.    }
  593.    if (CC.ExecuteFlag) {
  594.       if (INSIDE_BEGIN_END) {
  595.      gl_error( GL_INVALID_OPERATION, "glPopMatrix" );
  596.      return;
  597.       }
  598.       switch (CC.Transform.MatrixMode) {
  599.      case GL_MODELVIEW:
  600.         if (CC.ModelViewStackDepth>=MAX_MODELVIEW_STACK_DEPTH-1) {
  601.            gl_error( GL_STACK_OVERFLOW, "glPushMatrix");
  602.            return;
  603.         }
  604.         MEMCPY( CC.ModelViewStack[CC.ModelViewStackDepth],
  605.             CC.ModelViewMatrix,
  606.             16*sizeof(GLfloat) );
  607.         CC.ModelViewStackDepth++;
  608.         break;
  609.      case GL_PROJECTION:
  610.         if (CC.ProjectionStackDepth>=MAX_PROJECTION_STACK_DEPTH) {
  611.            gl_error( GL_STACK_OVERFLOW, "glPushMatrix");
  612.            return;
  613.         }
  614.         MEMCPY( CC.ProjectionStack[CC.ProjectionStackDepth],
  615.             CC.ProjectionMatrix,
  616.             16*sizeof(GLfloat) );
  617.         CC.ProjectionStackDepth++;
  618.         break;
  619.      case GL_TEXTURE:
  620.         if (CC.TextureStackDepth>=MAX_TEXTURE_STACK_DEPTH) {
  621.            gl_error( GL_STACK_OVERFLOW, "glPushMatrix");
  622.            return;
  623.         }
  624.         MEMCPY( CC.TextureStack[CC.TextureStackDepth],
  625.             CC.TextureMatrix,
  626.             16*sizeof(GLfloat) );
  627.         CC.TextureStackDepth++;
  628.         break;
  629.       }
  630.    }
  631. }
  632.  
  633.  
  634.  
  635. void glPopMatrix( void )
  636. {
  637.    if (CC.CompileFlag) {
  638.       gl_save_popmatrix();
  639.    }
  640.    if (CC.ExecuteFlag) {
  641.       if (INSIDE_BEGIN_END) {
  642.      gl_error( GL_INVALID_OPERATION, "glPopMatrix" );
  643.      return;
  644.       }
  645.       switch (CC.Transform.MatrixMode) {
  646.      case GL_MODELVIEW:
  647.         if (CC.ModelViewStackDepth==0) {
  648.            gl_error( GL_STACK_UNDERFLOW, "glPop");
  649.            return;
  650.         }
  651.         CC.ModelViewStackDepth--;
  652.         MEMCPY( CC.ModelViewMatrix,
  653.             CC.ModelViewStack[CC.ModelViewStackDepth],
  654.             16*sizeof(GLfloat) );
  655.         CC.ModelViewInvValid = GL_FALSE;
  656.         break;
  657.      case GL_PROJECTION:
  658.         if (CC.ProjectionStackDepth==0) {
  659.            gl_error( GL_STACK_UNDERFLOW, "glPop");
  660.            return;
  661.         }
  662.         CC.ProjectionStackDepth--;
  663.         MEMCPY( CC.ProjectionMatrix,
  664.             CC.ProjectionStack[CC.ProjectionStackDepth],
  665.             16*sizeof(GLfloat) );
  666.         break;
  667.      case GL_TEXTURE:
  668.         if (CC.TextureStackDepth==0) {
  669.            gl_error( GL_STACK_UNDERFLOW, "glPop");
  670.            return;
  671.         }
  672.         CC.TextureStackDepth--;
  673.         MEMCPY( CC.TextureMatrix,
  674.             CC.TextureStack[CC.TextureStackDepth],
  675.             16*sizeof(GLfloat) );
  676.             CC.IdentityTexMat = is_identity( CC.TextureMatrix );
  677.         break;
  678.       }
  679.    }
  680. }
  681.  
  682.  
  683.  
  684. void gl_load_matrix( const GLfloat *m )
  685. {
  686.    if (INSIDE_BEGIN_END) {
  687.       gl_error( GL_INVALID_OPERATION, "glLoadMatrix" );
  688.       return;
  689.    }
  690.    switch (CC.Transform.MatrixMode) {
  691.       case GL_MODELVIEW:
  692.          MEMCPY( CC.ModelViewMatrix, m, 16*sizeof(GLfloat) );
  693.      CC.ModelViewInvValid = GL_FALSE;
  694.      break;
  695.       case GL_PROJECTION:
  696.      MEMCPY( CC.ProjectionMatrix, m, 16*sizeof(GLfloat) );
  697.      break;
  698.       case GL_TEXTURE:
  699.      MEMCPY( CC.TextureMatrix, m, 16*sizeof(GLfloat) );
  700.          CC.IdentityTexMat = is_identity( CC.TextureMatrix );
  701.      break;
  702.    }
  703. }
  704.  
  705.  
  706.  
  707. void glLoadMatrixd( const GLdouble *m )
  708. {
  709.    GLfloat fm[16];
  710.    GLuint i;
  711.  
  712.    for (i=0;i<16;i++) {
  713.       fm[i] = (GLfloat) m[i];
  714.    }
  715.  
  716.    glLoadMatrixf( fm );
  717. }
  718.  
  719.  
  720.  
  721. void glLoadMatrixf( const GLfloat *m )
  722. {
  723.    if (CC.CompileFlag) {
  724.       gl_save_loadmatrix( m );
  725.    }
  726.    if (CC.ExecuteFlag) {
  727.       gl_load_matrix( m );
  728.    }
  729. }
  730.  
  731.  
  732.  
  733. void glLoadIdentity( void )
  734. {
  735.    if (CC.CompileFlag) {
  736.       gl_save_loadmatrix( Identity );
  737.    }
  738.    if (CC.ExecuteFlag) {
  739.       gl_load_matrix( Identity );
  740.    }
  741. }
  742.  
  743.  
  744.  
  745. void gl_mult_matrix( const GLfloat *m )
  746. {
  747.    if (INSIDE_BEGIN_END) {
  748.       gl_error( GL_INVALID_OPERATION, "glMultMatrix" );
  749.       return;
  750.    }
  751.    switch (CC.Transform.MatrixMode) {
  752.       case GL_MODELVIEW:
  753.          matmul( CC.ModelViewMatrix, CC.ModelViewMatrix, m );
  754.      CC.ModelViewInvValid = GL_FALSE;
  755.      break;
  756.       case GL_PROJECTION:
  757.      matmul( CC.ProjectionMatrix, CC.ProjectionMatrix, m );
  758.      break;
  759.       case GL_TEXTURE:
  760.      matmul( CC.TextureMatrix, CC.TextureMatrix, m );
  761.          CC.IdentityTexMat = is_identity( CC.TextureMatrix );
  762.      break;
  763.    }
  764. }
  765.  
  766.  
  767.  
  768. void glMultMatrixd( const GLdouble *m )
  769. {
  770.    GLfloat fm[16];
  771.    GLuint i;
  772.  
  773.    for (i=0;i<16;i++) {
  774.       fm[i] = (GLfloat) m[i];
  775.    }
  776.  
  777.    glMultMatrixf( fm );
  778. }
  779.  
  780.  
  781.  
  782. void glMultMatrixf( const GLfloat *m )
  783. {
  784.    if (CC.CompileFlag) {
  785.       gl_save_multmatrix( m );
  786.    }
  787.    if (CC.ExecuteFlag) {
  788.       gl_mult_matrix( m );
  789.    }
  790. }
  791.  
  792.  
  793.  
  794. void glRotated( GLdouble angle, GLdouble x, GLdouble y, GLdouble z )
  795. {
  796.    glRotatef( (GLfloat) angle, (GLfloat) x, (GLfloat) y, (GLfloat) z );
  797. }
  798.  
  799.  
  800.  
  801. void glRotatef( GLfloat angle, GLfloat x, GLfloat y, GLfloat z )
  802. {
  803.    /* This function contributed by Erich Boleyn (erich@uruk.org) */
  804.  
  805.    GLfloat m[16];
  806.    GLfloat mag, s, c;
  807.    GLfloat xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c;
  808.  
  809.    s = sin( angle * (M_PI / 180.0) );
  810.    c = cos( angle * (M_PI / 180.0) );
  811.  
  812.    mag = sqrt( x*x + y*y + z*z );
  813.  
  814.    if (mag == 0.0)
  815.      return;
  816.  
  817.    x /= mag;
  818.    y /= mag;
  819.    z /= mag;
  820.  
  821. #define M(row,col)  m[col*4+row]
  822.  
  823.    /*
  824.     *     Arbitrary axis rotation matrix.
  825.     *
  826.     *  This is composed of 5 matrices, Rz, Ry, T, Ry', Rz', multiplied
  827.     *  like so:  Rz * Ry * T * Ry' * Rz'.  T is the final rotation
  828.     *  (which is about the X-axis), and the two composite transforms
  829.     *  Ry' * Rz' and Rz * Ry are (respectively) the rotations necessary
  830.     *  from the arbitrary axis to the X-axis then back.  They are
  831.     *  all elementary rotations.
  832.     *
  833.     *  Rz' is a rotation about the Z-axis, to bring the axis vector
  834.     *  into the x-z plane.  Then Ry' is applied, rotating about the
  835.     *  Y-axis to bring the axis vector parallel with the X-axis.  The
  836.     *  rotation about the X-axis is then performed.  Ry and Rz are
  837.     *  simply the respective inverse transforms to bring the arbitrary
  838.     *  axis back to it's original orientation.  The first transforms
  839.     *  Rz' and Ry' are considered inverses, since the data from the
  840.     *  arbitrary axis gives you info on how to get to it, not how
  841.     *  to get away from it, and an inverse must be applied.
  842.     *
  843.     *  The basic calculation used is to recognize that the arbitrary
  844.     *  axis vector (x, y, z), since it is of unit length, actually
  845.     *  represents the sines and cosines of the angles to rotate the
  846.     *  X-axis to the same orientation, with theta being the angle about
  847.     *  Z and phi the angle about Y (in the order described above)
  848.     *  as follows:
  849.     *
  850.     *  cos ( theta ) = x / sqrt ( 1 - z^2 )
  851.     *  sin ( theta ) = y / sqrt ( 1 - z^2 )
  852.     *
  853.     *  cos ( phi ) = sqrt ( 1 - z^2 )
  854.     *  sin ( phi ) = z
  855.     *
  856.     *  Note that cos ( phi ) can further be inserted to the above
  857.     *  formulas:
  858.     *
  859.     *  cos ( theta ) = x / cos ( phi )
  860.     *  sin ( theta ) = y / sin ( phi )
  861.     *
  862.     *  ...etc.  Because of those relations and the standard trigonometric
  863.     *  relations, it is pssible to reduce the transforms down to what
  864.     *  is used below.  It may be that any primary axis chosen will give the
  865.     *  same results (modulo a sign convention) using thie method.
  866.     *
  867.     *  Particularly nice is to notice that all divisions that might
  868.     *  have caused trouble when parallel to certain planes or
  869.     *  axis go away with care paid to reducing the expressions.
  870.     *  After checking, it does perform correctly under all cases, since
  871.     *  in all the cases of division where the denominator would have
  872.     *  been zero, the numerator would have been zero as well, giving
  873.     *  the expected result.
  874.     */
  875.  
  876.    xx = x * x;
  877.    yy = y * y;
  878.    zz = z * z;
  879.    xy = x * y;
  880.    yz = y * z;
  881.    zx = z * x;
  882.    xs = x * s;
  883.    ys = y * s;
  884.    zs = z * s;
  885.    one_c = 1.0F - c;
  886.  
  887.    M(0,0) = (one_c * xx) + c;
  888.    M(0,1) = (one_c * xy) - zs;
  889.    M(0,2) = (one_c * zx) + ys;
  890.    M(0,3) = 0.0F;
  891.  
  892.    M(1,0) = (one_c * xy) + zs;
  893.    M(1,1) = (one_c * yy) + c;
  894.    M(1,2) = (one_c * yz) - xs;
  895.    M(1,3) = 0.0F;
  896.  
  897.    M(2,0) = (one_c * zx) - ys;
  898.    M(2,1) = (one_c * yz) + xs;
  899.    M(2,2) = (one_c * zz) + c;
  900.    M(2,3) = 0.0F;
  901.  
  902.    M(3,0) = 0.0F;
  903.    M(3,1) = 0.0F;
  904.    M(3,2) = 0.0F;
  905.    M(3,3) = 1.0F;
  906.  
  907. #undef M
  908.  
  909.    if (CC.CompileFlag) {
  910.       gl_save_multmatrix( m );
  911.    }
  912.    if (CC.ExecuteFlag) {
  913.       gl_mult_matrix( m );
  914.    }
  915. }
  916.  
  917.  
  918.  
  919. void glScaled( GLdouble x, GLdouble y, GLdouble z )
  920. {
  921.    glScalef( (GLfloat) x, (GLfloat) y, (GLfloat) z );
  922. }
  923.  
  924.  
  925.  
  926. void glScalef( GLfloat x, GLfloat y, GLfloat z )
  927. {
  928.    GLfloat m[16];
  929.  
  930. #define M(row,col)  m[col*4+row]
  931.    M(0,0) = x;     M(0,1) = 0.0F;  M(0,2) = 0.0F;  M(0,3) = 0.0F;
  932.    M(1,0) = 0.0F;  M(1,1) = y;     M(1,2) = 0.0F;  M(1,3) = 0.0F;
  933.    M(2,0) = 0.0F;  M(2,1) = 0.0F;  M(2,2) = z;     M(2,3) = 0.0F;
  934.    M(3,0) = 0.0F;  M(3,1) = 0.0F;  M(3,2) = 0.0F;  M(3,3) = 1.0F;
  935. #undef M
  936.  
  937.    if (CC.CompileFlag) {
  938.       gl_save_multmatrix( m );
  939.    }
  940.    if (CC.ExecuteFlag) {
  941.       gl_mult_matrix( m );
  942.    }
  943. }
  944.  
  945.  
  946.  
  947.  
  948. void glTranslated( GLdouble x, GLdouble y, GLdouble z )
  949. {
  950.    glTranslatef( (GLfloat) x, (GLfloat) y, (GLfloat) z );
  951. }
  952.  
  953.  
  954.  
  955. void glTranslatef( GLfloat x, GLfloat y, GLfloat z )
  956. {
  957.    GLfloat m[16];
  958.  
  959. #define M(row,col)  m[col*4+row]
  960.    M(0,0) = 1.0F;  M(0,1) = 0.0F;  M(0,2) = 0.0F;  M(0,3) = x;
  961.    M(1,0) = 0.0F;  M(1,1) = 1.0F;  M(1,2) = 0.0F;  M(1,3) = y;
  962.    M(2,0) = 0.0F;  M(2,1) = 0.0F;  M(2,2) = 1.0F;  M(2,3) = z;
  963.    M(3,0) = 0.0F;  M(3,1) = 0.0F;  M(3,2) = 0.0F;  M(3,3) = 1.0F;
  964. #undef M
  965.  
  966.    if (CC.CompileFlag) {
  967.       gl_save_multmatrix( m );
  968.    }
  969.    if (CC.ExecuteFlag) {
  970.       gl_mult_matrix( m );
  971.    }
  972. }
  973.